﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using NPOI.XWPF.UserModel;
using System.IO;
using System.Threading;

namespace AutoShuXue
{
    public partial class Form1 : Form
    {
        int n = 18;//每列题目数，共两列,,,
        string fileName;

        int k = 5;//每列题目中的无需进位的题目数
        

        List<int> answerList; //答案列表
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            lblMsg.Visible = false;
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            if (!lblMsg.Visible) lblMsg.Visible = true;
            btnGenerate.Enabled = false;
            answerList = new List<int>();

            Thread thread = new Thread(AutoGenerate);
            try
            {
                thread.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void AutoGenerate()
        {
            this.Invoke((EventHandler)delegate
            {
                lblMsg.Text = "数学题自动生成中...";
                lklOpenFile.Visible = false;
            });

            
            List<string> list2 = new List<string>();//两数算式列表
            List<string> list3 = new List<string>();//三数算式列表

            List<int> noTen2 = new List<int>();
            List<int> noTen3 = new List<int>();

            for (int i = 0; i < k; i++)
            {
                
                Random r = new Random();
                int x;

                do
                {
                    x = r.Next(0, 18);
                } while (noTen2.Contains(x));
                noTen2.Add(x);

                do
                {
                    x = r.Next(0, 18);
                } while (noTen3.Contains(x));
                noTen3.Add(x);
            }

            for (int i = 0; i < n; i++)
            {
                Thread.Sleep(50);//运算时间过快，会导致随机数相同，算式都是同一个
                string exp;
                int ans;

                if (noTen2.Contains(i))
                {
                    do
                    {
                    } while (!CreateTwoNumber2(out exp, out ans));
                }
                else
                {
                    do
                    {
                    } while (!CreateTwoNumber(out exp, out ans));
                }

                this.Invoke((EventHandler)delegate
                {
                    this.progressBar1.Value = (int)(((float)i + 1) / 36 * 100);
                });
                list2.Add(exp);
                answerList.Add(ans);
            }


            for (int i = 0; i < n; i++)
            {
                Thread.Sleep(50);
                string exp;
                int ans;
                

                if (noTen3.Contains(i))
                {
                    do
                    {
                    } while (!CreateThreeNumber2(out exp, out ans));
                }
                else
                {
                    do
                    {
                    } while (!CreateThreeNumber(out exp, out ans));
                }

                this.Invoke((EventHandler)delegate
                {
                    this.progressBar1.Value = (int)(((float)i + 19) / 36 * 100);
                });
                list3.Add(exp);
                answerList.Add(ans);
            }
            //构建并生成文件
            GenerateDoc(list2, list3);

            //完成

            this.Invoke((EventHandler)delegate
            {
                lblMsg.Text = "数学题生成完毕.";
                btnGenerate.Text = "再次生成";
                lklOpenFile.Visible = true;
                btnGenerate.Enabled = true;
            });

        }

        /// <summary>
        /// 两个数字的表达式,有进位或退位
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private bool CreateTwoNumber(out string expression, out int answer)
        {
            //Thread.Sleep(500);
            Random r = new Random();
            int x = r.Next(11, 100);
            int x1 = x % 10;
            int op = r.Next(0, 2);//0-,1+
            int y = r.Next(11, 100);
            int y1 = y % 10;

            if (op == 1)//加法
            {
                if (x1 + y1 >= 10 && x + y < 100)
                {
                    expression = x.ToString() + " + " + y.ToString() + " = ";
                    answer = x + y;
                    return true;
                }
            }
            else if (op == 0) //减法
            {
                if (x - y > 10 && x1 < y1)
                {
                    expression = x.ToString() + " - " + y.ToString() + " = ";
                    answer = x - y;
                    return true;
                }
            }
            expression = "";
            answer = -1;
            return false;
        }

        /// <summary>
        /// 两个数字的表达式,无进位或退位
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private bool CreateTwoNumber2(out string expression, out int answer)
        {
            //Thread.Sleep(500);
            Random r = new Random();
            int x = r.Next(11, 100);
            int x1 = x % 10;
            int op = r.Next(0, 2);//0-,1+
            int y = r.Next(11, 100);
            int y1 = y % 10;

            if (op == 1)//加法
            {
                if (x1 + y1 < 10 && x + y < 100)
                {
                    expression = x.ToString() + " + " + y.ToString() + " = ";
                    answer = x + y;
                    return true;
                }
            }
            else if (op == 0) //减法
            {
                if (x - y > 10 && x1 >= y1)
                {
                    expression = x.ToString() + " - " + y.ToString() + " = ";
                    answer = x - y;
                    return true;
                }
            }
            expression = "";
            answer = -1;
            return false;
        }

        /// <summary>
        /// 三个数字的表达式
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private bool CreateThreeNumber(out string expression, out int answer)
        {
            Random r = new Random();
            int x = r.Next(11, 100);
            int y = r.Next(11, 100);
            int z = r.Next(11, 100);
            int x1 = x % 10;
            int y1 = y % 10;
            int z1 = z % 10;
            int op1 = r.Next(0, 2);//0-,1+
            int op2 = r.Next(0, 2);

            int m;
            int m1;

            if (op1 == 1)//加法
            {
                if (x1 + y1 >= 10 && x + y < 100)
                {
                    m = x + y;
                    m1 = m % 10;
                    if (op2 == 1 && m1 + z1 >= 10 && m + z < 100)
                    {
                        expression = x.ToString() + " + " + y.ToString() + " + " + z.ToString() + " = ";
                        answer = x + y + z;
                        return true;
                    }
                    else if (op2 == 0 && m - z > 0 && m1 < z1)
                    {
                        expression = x.ToString() + " + " + y.ToString() + " - " + z.ToString() + " = ";
                        answer = x + y - z;
                        return true;
                    }

                }
            }
            else if (op1 == 0) //减法
            {
                if (x > y && x1 < y1)
                {
                    m = x - y;
                    m1 = m % 10;

                    if (op2 == 1 && m1 + z1 >= 10 && m + z < 100)
                    {
                        expression = x.ToString() + " - " + y.ToString() + " + " + z.ToString() + " = ";
                        answer = x - y + z;
                        return true;
                    }
                    else if (op2 == 0 && m - z > 0 && m1 < z1)
                    {
                        expression = x.ToString() + " - " + y.ToString() + " - " + z.ToString() + " = ";
                        answer = x - y - z;
                        return true;
                    }
                }
            }
            expression = "";
            answer = -1;
            return false;
        }

        /// <summary>
        /// 三个数字的表达式,没有进位
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private bool CreateThreeNumber2(out string expression, out int answer)
        {
            Random r = new Random();
            int x = r.Next(11, 100);
            int y = r.Next(11, 100);
            int z = r.Next(11, 100);
            int x1 = x % 10;
            int y1 = y % 10;
            int z1 = z % 10;
            int op1 = r.Next(0, 2);//0-,1+
            int op2 = r.Next(0, 2);

            int m;
            int m1;

            if (op1 == 1)//加法
            {
                if (x1 + y1 < 10 && x + y < 100)
                {
                    m = x + y;
                    m1 = m % 10;
                    if (op2 == 1 && m1 + z1 < 10 && m + z < 100)
                    {
                        expression = x.ToString() + " + " + y.ToString() + " + " + z.ToString() + " = ";
                        answer = x + y + z;
                        return true;
                    }
                    else if (op2 == 0 && m - z > 0)
                    {
                        expression = x.ToString() + " + " + y.ToString() + " - " + z.ToString() + " = ";
                        answer = x + y - z;
                        return true;
                    }

                }
            }
            else if (op1 == 0) //减法
            {
                if (x > y)
                {
                    m = x - y;
                    m1 = m % 10;

                    if (op2 == 1 && m1 + z1 < 10 && m + z < 100)
                    {
                        expression = x.ToString() + " - " + y.ToString() + " + " + z.ToString() + " = ";
                        answer = x - y + z;
                        return true;
                    }
                    else if (op2 == 0 && m - z > 0)
                    {
                        expression = x.ToString() + " - " + y.ToString() + " - " + z.ToString() + " = ";
                        answer = x - y - z;
                        return true;
                    }
                }
            }
            expression = "";
            answer = -1;
            return false;
        }

        /// <summary>
        /// 构建文件
        /// </summary>
        /// <param name="list2"></param>
        /// <param name="list3"></param>
        private void GenerateDoc(List<string> list2, List<string> list3)
        {
            //Title
            XWPFDocument doc = new XWPFDocument();
            XWPFParagraph para = doc.CreateParagraph();
            XWPFRun r = para.CreateRun();
            r.SetText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

            //Table
            XWPFTable table = doc.CreateTable(n, 4);
            table.SetInsideHBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, "");
            table.SetInsideVBorder(XWPFTable.XWPFBorderType.NONE, 0, 0, "");
            table.Width = 5000;
            table.SetColumnWidth(0, 100);
            table.SetColumnWidth(2, 100);
            table.SetColumnWidth(1, 2500);
            table.SetColumnWidth(3, 2500);
            for (int i = 0; i < n; i++)
            {
                var row = table.GetRow(i);
                row.Height = 600;

                SetCell(table.GetRow(i).GetCell(0), 11, "(" + (i + 1).ToString() + ")");
                SetCell(table.GetRow(i).GetCell(2), 11, "(" + (n + i + 1).ToString() + ")");
                SetCell(table.GetRow(i).GetCell(1), 15, list2[i]);
                SetCell(table.GetRow(i).GetCell(3), 15, list3[i]);
            }

            //答案
            var para2 = doc.CreateParagraph();
            var run2 = para2.CreateRun();
            run2.AddBreak(BreakType.PAGE);
            run2.SetText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
            XWPFTable table2 = doc.CreateTable(4, 11);
            table2.Width = 5000;

            for (int i = 0; i < 4; i++)
            {
                table2.GetRow(i).GetCell(0).SetColor("FFFF00");
                table2.GetRow(i).GetCell(0).SetText((i * 10 + 1).ToString() + "-" + ((i + 1) * 10).ToString());
                for (int j = 6; j < 11; j++)
                {
                    table2.GetRow(i).GetCell(j).SetColor("D3D3D3");
                }
            }
            for (int i = 0; i < 36; i++)
            {
                table2.GetRow(i / 10).GetCell(i % 10 + 1).SetText(answerList[i].ToString());
            }

            //输出文件
            fileName = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss_fff") + ".docx";
            FileStream out1 = new FileStream(fileName, FileMode.Create);
            doc.Write(out1);
            out1.Close();
        }

        public void SetCell(XWPFTableCell cell, int fontSize, string txt)
        {
            var para = cell.AddParagraph();
            var run = para.CreateRun();
            run.FontSize = fontSize;
            run.SetText(txt);
        }



        private void lklOpenFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var file = System.Environment.CurrentDirectory + "\\" + fileName;
            try
            {
                System.Diagnostics.Process.Start(file);//Word
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
    }
}
